<template>
  <div id="message_detail_success">
    <header class="flex-left-right f-mb20">
      <span class="detail_title f-mr12" style=" white-space: nowrap;display:flex;width:1060px">
        请求URL:
        <ga-tooltip :title="data.contentKey" position="l">
          <ga-tag style="
                                    color: var(--default-text-color);
                                    margin-left: 4px;
                                ">
            {{ data.contentKey }}
          </ga-tag>
        </ga-tooltip>
        <template v-show="data.traceId">
          traceid:
          <ga-tooltip :title="data.traceId" position="l">

            <ga-tag style="color: var(--default-text-color); margin-left: 4px; text-overflow:ellipsis;
              white-space:nowrap; overflow:hidden">
              {{ data.traceId }}
            </ga-tag>
          </ga-tooltip>
        </template>
      </span>

    </header>
    <div ref="topoRef" id="message_topo" class="message_topo" style="height: 270px "></div>

  </div>
</template>

<script setup>
import { getExceptionTopo } from '@/api/exceptionDetail';
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import {find,maxBy } from 'lodash'
import { handleTopoData,graphFocusNodeNew } from './topoServices';

const nameTooltip = new G6.Tooltip({
  offestX: 10,
  offestY: 10,
  itemTypes: ["node"],
  getContent: (e) => {
    const targetName = e.target.get("name");
    const node = e.item.getModel();
    if (targetName === "node-name") {
      const name = node.workloadName || `${node.ip}${node.port ? `:${node.port}` : ""}`
      // return name
      return (

        `<span style="display:inline-block; max-width:200px;word-wrap:break-word">${name}</span>`
      );
    }
    if (targetName === "node-cluster-namespace") {
      return `${node.clusterName}(${node.namespace})`;
    }
    return "";
  },
  shouldBegin: (e) => {
    const targetName = e.target.get("name");
    if (
      targetName === "node-name" ||
      targetName === "node-cluster-namespace"
    ) {
      return true;
    }
    return false;
  },
});
const props = defineProps({
  timeInfo: {
    type: Object,
    default: () => ({})
  },
  data: {
    type: Object,
    default: () => ({})
  },

})
const emits = defineEmits(['on-select-edge'])
const { query } = useRoute()
const topoRef = ref()
const graphInstance = ref()
const topoData = ref({ nodes: [], edges: [] })
const edgeInfo = ref({})
const urlInfo = ref({})
// 当监听到window对象或者container的大小发生变化是，改变画布大小
const changeGraphSize = () => {
  if (topoRef.value && graphInstance.value) {
    const { clientWidth, clientHeight } = topoRef.value;
    graphInstance.value.changeSize(clientWidth, clientHeight);
    // this.graph.fitCenter()
  }
};
const getTopoData = () => {
  const { data, timeInfo } = props;
  if (!data.traceId) {
    topoData.value = {nodes:[], edges:[]}
    return;
  }
  const { from, to } = timeInfo;
  const { masterIp, traceId } = data;
  const params = {
    from,
    to,
    traceId,
    masterIp: data?.srcMasterip?.key,
  };
  console.log(params, "params");

  getExceptionTopo(params).then((res) => {
    console.log(res, "res");

    const { nodes, edges } = handleTopoData(
      res.data.data || [],
      data
    );
    const nowEdge = find(edges, { isNowRequest: true }) || {};
    const maxRequestTotalTimeItem = maxBy(
      nowEdge?.urlList || [],
      "requestTotalTime"
    );
    topoData.value = {nodes,edges},
    // edgeInfo.value = nowEdge ||  {}
    // urlInfo.value = maxRequestTotalTimeItem || data
    draw()
  });
};
const draw = () => {
  const topoData = cloneDeep(topoData.value);
  if (!topoData.nodes.length) {
    topoRef.value.innerHTML = "";
    return;
  }
  const { nodes, edges } = topoData;
  const data = { nodes, edges };

  const width = topoRef.value.clientWidth;
  const height = topoRef.value.clientHeight;
  topoRef.value.innerHTML = "";

  const graph = new G6.Graph({
    container: "message_topo",
    width,
    height,
    fitCenter: true,
    autoPaint: false,
    plugins: [nameTooltip],
    modes: {
      default: [
        {
          type: "zoom-canvas",
          minZoom: 0.5,
          maxZoom: 5,
        },
        {
          type: "drag-node",
          onlyChangeComboSize: true,
        },
        "drag-combo",
        "drag-canvas",
      ],
      showComponent: [],
    },
    defaultNode: {
      type: "custom-message-topo-node",
    },
    defaultEdge: {
      type: "custom-message-topo-edge",
      style: {
        // radius: 10,
        // offset: 45,
        endArrow: {
          path: G6.Arrow.triangle(10, 10, 0),
          fill: "#aaa",
        },
        lineWidth: 2,
        stroke: "#aaa",
        cursor: "pointer",
      },
    },
    layout: {
      type: "dagre",
      rankdir: "LR",
      nodesep: 30,
      ranksep: 40,
    },
  });
  graph.data(data);
  graph.render();

  graphInstance.value = graph;
  graph.fitCenter();
  graph.on("node:mouseenter", (evt) => {
    const { item } = evt;
    graphFocusNodeNew(item, graph);
    graph.setItemState(item, "active", true);
  });
  graph.on("node:mouseleave", (evt) => {
    const { item } = evt;
    graphFocusNodeNew("", graph);
    graph.setItemState(item, "active", false);
  });
  graph.on("edge:click", (evt) => {
    const { item } = evt;
    // console.log(evt, 'evt');

    const model = item.getModel();
    const maxRequestTotalTimeItem = maxBy(
      model?.urlList || [],
      "requestTotalTime"
    );
    const src = item.getSource().getModel();
    const dst = item.getTarget().getModel();
    const params = {
      dstWorkloadName: dst?.workloadName,
      dstNamespace: dst?.namespace,
      dstWorkloadKind: dst?.workloadKind,
      dstMasterIp: dst?.masterIp,
      srcWorkloadList: [src],
    };
    const netParams = {
      dstWorkloadName: dst?.workloadName,
      dstNamespace: dst?.namespace,
      dstWorkloadKind: dst?.workloadKind,
      dstMasterIp: dst?.masterIp,

      srcWorkloadList: [src],
    };
    const timeParams = {
      traceId: model.id
    }
    console.log(src, "src", dst, "dst", this.props);
    // this.props.selectEdge(params, netParams, timeParams)
    emits('on-select-edge', params, netParams, timeParams)
    // edgeInfo.value = model
    // urlInfo.value = maxRequestTotalTimeItem || {}
    setEdgeLineWidth(graph);

  });

  setEdgeLineWidth(graph);
}
// afterrender后设置线的粗细
const setEdgeLineWidth = (graph) => {

  graph.setAutoPaint(false);
  const edges = graph.getEdges();
  forEach(edges, (edge) => {
    const edgeModel = edge.getModel();
    const { requestTotalTime } = edgeModel;
    const slowThreshold = Number(props.slowThreshold) * 1000000;
    const lineWidth =
      edgeModel.source === edgeInfo.value?.srcWorkloadKey &&
        edgeModel.target === edgeInfo.value?.dstWorkloadKey
        ? 5
        : 2;

    edgeModel.style.stroke =
      requestTotalTime > slowThreshold ? "#F7313B" : "#aaa";
    edgeModel.style.lineWidth = lineWidth;
    edgeModel.style.endArrow = {
      path: G6.Arrow.triangle(10, 10, 0),
      fill: requestTotalTime > slowThreshold ? "#F7313B" : "#aaa",
    };
    graph.updateItem(edge, edgeModel);
  });
  graph.paint();
  graph.setAutoPaint(true);
};
watch([() => props.data, () => props.timeInfo], () => {
  getTopoData()
})
onMounted(() => {
  window.addEventListener('resize', changeGraphSize)
})
onUnmounted(() => {
  window.removeEventListener('resize', changeGraphSize)
})
</script>

<style scoped lang="scss"></style>
